/*
	MO
	javascript framework
	author:
		Wiki[MO]	gwikimo@gmail.com	
		Lay 			veryide@qq.com
*/

//(function(){

	var Mo = function (obj){		
		return new Mo.init(obj);
	}
	
	/*
		Mo版本号
	*/
	Mo.version = "1.2 Beta";
	
	/*
		最后更新时间
	*/	
	Mo.build = 20110124;
	
	/*
		临时对象
	*/
	Mo.store = new Object();
	
	
	/*
		全局变量生成
	*/
	Mo.start = function(){

		/*
			浏览器
		*/
		Mo.Browser = {
			msie : false,
			opera : false,
			safari : false,			
			chrome : false,			
			firefox : false
		};

		/*
			浏览器版本
		*/
		var nav = navigator;
		var reg = '';
		
		switch ( nav.appName ){
			
			case "Microsoft Internet Explorer":{
			
				Mo.Browser.name = "ie";
				var reg = /^.+MSIE (\d+\.\d+);.+$/;
				Mo.Browser.msie = true;
				
			break;
			
			}default:{
				if (nav.userAgent.indexOf("Chrome") != -1){
					Mo.Browser.name = "chrome";
					Mo.Browser.chrome=true;					
					reg = /^.+Chrome\/([\d.]+?)([\s].*)$/ig;
					
				}else if (nav.userAgent.indexOf("Safari") != -1){
					Mo.Browser.name = "safari";
					Mo.Browser.safari=true;
					reg = /^.+Version\/([\d\.]+?) Safari.+$/;
					
				}else if (nav.userAgent.indexOf("Opera") != -1){
					Mo.Browser.name = "opera";
					Mo.Browser.opera=true;
					reg = /^.{0,}Opera\/(.+?) \(.+$/;
					
				}else{
					Mo.Browser.name = "firefox";
					Mo.Browser.firefox=true;
					reg = /^.+Firefox\/([\d\.]+).{0,}$/;
					
				}
			}
			break;
		}
		
		Mo.Browser.version = nav.userAgent.replace(reg, "$1");

		/*
			客户端语言
		*/		
		Mo.Browser.lang = ( !Mo.Browser.msie ? nav.language : nav.browserLanguage ).toLowerCase();
		
		/*
			是否为移动设备
		*/
		Mo.Browser.mobile = /\((iPhone|iPad|iPod)/i.test(nav.userAgent);
		
		/*
			页面主体
		*/	
		Mo.document = document.compatMode == "CSS1Compat" ? document.documentElement : document.body;
	}
	
	Mo.start();
	
	/*********************/

	/*
		页面DOM载入后执行
		func	函数块
	*/	
	Mo.ready = function( func ) {
		
		if ( Mo.Browser.msie ) {
		
			//check IE's proprietary DOM members
			//if (!document.uniqueID && document.expando) return; 
			
			Mo.store._dri = setInterval(function() {
			
				try {
					// throws an error if doc is not ready
					document.documentElement.doScroll('left');
					
					clearInterval(Mo.store._dri);					
					Mo.store._dri = null;
					
					func();
					
				} catch (ex) {
				
				}
				
			}, 0);
		
		}else{
			document.addEventListener("DOMContentLoaded", func , false);
		}
		
	}
	

	/*
		页面完全载入后执行
		func	函数块
	*/	
	Mo.reader = function( func ){
		var oldonload = window.onload;
		if (typeof window.onload != 'function') {
			window.onload = func;
		}else {
			window.onload = function() {
				oldonload();
				func();
			}
		}
	};

	/*
		页面改变后执行
		func	函数块
	*/	
	Mo.resize = function(func) {
		var oldonload = window.onresize;
		if (typeof window.onresize != 'function') {
			window.onresize = func;
		}else {
			window.onresize = function() {
				oldonload();
				func();
			}
		}
	}
	
	/*********************/
	
	/*
		格式化日期
		format		格式字符串
		datetime	日期，默认为当前日期
	*/
	Mo.date = function( format , datetime ){
		var str = format;
		var now = datetime ? datetime : new Date();
		var y = now.getFullYear(),
				m = now.getMonth()+1,
				d = now.getDate(),
				h = now.getHours(),
				i = now.getMinutes(),
				s = now.getSeconds();

		str = str.replace('yy',y.toString().substr(y.toString().length-2));
		str = str.replace('y',y);
		str = str.replace('mm',('0'+m).substr(m.toString().length-1));
		str = str.replace('m',m);
		str = str.replace('dd',('0'+d).substr(d.toString().length-1));
		str = str.replace('d',d);
		str = str.replace('hh',('0'+h).substr(h.toString().length-1));
		str = str.replace('h',h);
		str = str.replace('ii',('0'+i).substr(i.toString().length-1));
		str = str.replace('i',i);
		str = str.replace('ss',('0'+s).substr(s.toString().length-1));
		str = str.replace('s',s);

		return str;
	}
	
	/*
		获取随机字符
		length	长度 
		upper		是否允许大写字母 
		lower		是否允许小写字母 
		number	是否允许数字
	*/
	Mo.random = function(length,upper,lower,number){

		if( !upper && !lower && !number ){
			upper = lower = number = true;
		}
		
		var a = [
			["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"],
			["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"],
			["0","1","2","3","4","5","6","7","8","9"]
		];
			
		//临时数组
		var b = [""];
		
		//临时字串 
		var c = "";

		b = upper ? b.concat(a[0]) : b;
		b = lower ? b.concat(a[1]) : b;
		b = number ? b.concat(a[2]) : b;

		for (var i=0;i<length;i++){ 
			c += b[Math.round(Math.random()*(b.length-1))];
		}

		return c; 
	}

	/*
		返回两个数值之间的一个随机值
		min	最小值
		max	最大值
	*/
	Mo.between = function(min,max){
		return Math.round(min+(Math.random()*(max-min)));
		//return ( min && max ) ? Math.round(min+(Math.random()*(max-min))) : Math.random();
	}

	/*
		返回解码后的字符串
		string		源字符串
	*/
	Mo.htmlDecode = function(string){
		return (string == null)?string:string.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&").replace(/&quot;/g,"\"");
	}
	
	/*
		返回解码后的字符串
		string		源字符串
	*/
	Mo.htmlEncode = function(string){
		return (string == null)?string:string.replace(/&/g,"&amp;").replace(/\"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
	}
	
	/*
		输出内容到页面
		html	源代码
	*/
	Mo.write = function(html){
		document.write(html);
	}	
	
	/*
		解析URL地址
		myURL.file;     // = 'index.html'  	
		myURL.hash;     // = 'top'  	
		myURL.host;     // = 'abc.com'  	
		myURL.query;    // = '?id=255&m=hello'  	
		myURL.params;   // = Object = { id: 255, m: hello }  	
		myURL.path;     // = '/dir/index.html'  	
		myURL.segments; // = Array = ['dir', 'index.html']  	
		myURL.port;     // = '8080'  	
		myURL.protocol; // = 'http'  	
		myURL.source;   // = 'http://abc.com:8080/dir/index.html?id=255&m=hello#top' 
	*/	
	Mo.url = function(url) {  	
		var a =  document.createElement('a');  	
		a.href = url;  	
		return {  	
			source: url,	
			protocol: a.protocol.replace(':',''),	
			host: a.hostname,	
			port: a.port,  	
			query: a.search,  	
			params: (function(){  	
				var ret = {},  	
					seg = a.search.replace(/^\?/,'').split('&'),  	
					len = seg.length, i = 0, s;  	
				for (;i<len;i++) {  	
					if (!seg[i]) { continue; }  	
					s = seg[i].split('=');  	
					ret[s[0]] = s[1];  	
				}  	
				return ret;  
			})(),  
	
			file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1], 	
			hash: a.hash.replace('#',''),  	
			path: a.pathname.replace(/^([^\/])/,'/$1'),  	
			relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],  	
			segments: a.pathname.replace(/^\//,'').split('/')  	
		};  	
	}
	
	//////////////////////////////////// Mo.xml() ////////////////////////////////////////
	//See http://www.openjs.com/scripts/xml_parser/
	var not_whitespace = new RegExp(/[^\s]/);//This can be given inside the funciton - I made it a global variable to make the scipt a little bit faster.
	var parent_count;
	//Process the xml data
	Mo.xml = function(xmlDoc,parent_count) {
		var arr;
		var parent = "";
		parent_count = parent_count || new Object;

		var attribute_inside = 0;
		/*:CONFIG: Value - 1 or 0
		*	If 1, Value and Attribute will be shown inside the tag - like this...
		*	For the XML string...
		*	<guid isPermaLink="true">http://www.bin-co.com/</guid>
		*	The resulting array will be...
		*	array['guid']['value'] = "http://www.bin-co.com/";
		*	array['guid']['attribute_isPermaLink'] = "true";
		*	
		*	If 0, the value will be inside the tag but the attribute will be outside - like this...	
		*	For the same XML String the resulting array will be...
		*	array['guid'] = "http://www.bin-co.com/";
		*	array['attribute_guid_isPermaLink'] = "true";
		*/

		if(xmlDoc.nodeName && xmlDoc.nodeName.charAt(0) != "#") {
			if(xmlDoc.childNodes.length > 1) { //If its a parent
				arr = new Object;
				parent = xmlDoc.nodeName;
				
			}
		}
		var value = xmlDoc.nodeValue;
		if(xmlDoc.parentNode && xmlDoc.parentNode.nodeName && value) {
			if(not_whitespace.test(value)) {//If its a child
				arr = new Object;
				arr[xmlDoc.parentNode.nodeName] = value;
			}
		}

		if(xmlDoc.childNodes.length) {
			if(xmlDoc.childNodes.length == 1) { //Just one item in this tag.
				arr = Mo.xml(xmlDoc.childNodes[0],parent_count); //:RECURSION:
			} else { //If there is more than one childNodes, go thru them one by one and get their results.
				var index = 0;

				for(var i=0; i<xmlDoc.childNodes.length; i++) {//Go thru all the child nodes.
					var temp = Mo.xml(xmlDoc.childNodes[i],parent_count); //:RECURSION:
					if(temp) {
						var assoc = false;
						var arr_count = 0;
						for(key in temp) {
							if(isNaN(key)) assoc = true;
							arr_count++;
							if(arr_count>2) break;//We just need to know wether it is a single value array or not
						}

						if(assoc && arr_count == 1) {
							if(arr[key]) { 	//If another element exists with the same tag name before,
											//		put it in a numeric array.
								//Find out how many time this parent made its appearance
								if(!parent_count || !parent_count[key]) {
									parent_count[key] = 0;

									var temp_arr = arr[key];
									arr[key] = new Object;
									arr[key][0] = temp_arr;
								}
								parent_count[key]++;
								arr[key][parent_count[key]] = temp[key]; //Members of of a numeric array
							} else {
								parent_count[key] = 0;
								arr[key] = temp[key];
								if(xmlDoc.childNodes[i].attributes && xmlDoc.childNodes[i].attributes.length) {
									for(var j=0; j<xmlDoc.childNodes[i].attributes.length; j++) {
										var nname = xmlDoc.childNodes[i].attributes[j].nodeName;
										if(nname) {
											/* Value and Attribute inside the tag */
											if(attribute_inside) {
												var temp_arr = arr[key];
												arr[key] = new Object;
												arr[key]['value'] = temp_arr;
												arr[key]['attribute_'+nname] = xmlDoc.childNodes[i].attributes[j].nodeValue;
											} else {
											/* Value in the tag and Attribute otside the tag(in parent) */
												arr['attribute_' + key + '_' + nname] = xmlDoc.childNodes[i].attributes[j].nodeValue;
											}
										}
									} //End of 'for(var j=0; j<xmlDoc. ...'
								} //End of 'if(xmlDoc.childNodes[i] ...'
							}
						} else {
							arr[index] = temp;
							index++;
						}
					} //End of 'if(temp) {'
				} //End of 'for(var i=0; i<xmlDoc. ...'
			}
		}

		if(parent && arr) {
			var temp = arr;
			arr = new Object;
			
			arr[parent] = temp;
		}
		return arr;
	}
	
	/*
		获取或设置Cookie
		key	名称
		value	值
		days	多少天有效
		domain	域
		path	路径
	*/
	/*
	Mo.cookie = function( key , value , days , domain , path ){
	
		//value 未定义则为获取值
		if( typeof value == "undefined" ){
			var str="";
			var arr = document.cookie.replace(/%25/g,"%").replace(/%5F/g,"_").match(new RegExp("(^| )"+key+"=([^;]*)(;|$)"));
			if(arr !=null){
				try{
					str=decodeURIComponent(arr[2]);
				}catch(e){
					str=arr[2];
				}
			}
	
			return str;
			
		//设置cookie值
		}else{
		
			var cookies=key.replace("_","%5F") + "=" + encodeURIComponent(value)+ "; ";
			if (days){
				var dExpire = new Date();
				dExpire.setTime(dExpire.getTime()+parseInt(days*24*60*60*1000));
				cookies += "expires=" + dExpire.toGMTString()+ "; ";
			}
			domain ? cookies += "domain="+domain+";" : "";
			path ? cookies += "path="+path+";" : "/";
			document.cookie = cookies;
		
		}	

	}
	
	*/
	
	/**
	 * @author 	Maxime Haineault (max@centdessin.com)
	 * @version	0.3
	 * @desc 	JavaScript cookie manipulation class
	 * 
	 */
	
	Mo.Cookie = {	
	
		/** Get a cookie's value
		 *
		 *  @param integer	key		The token used to create the cookie
		 *  @return void
		 */
		get: function(key) {
			// Still not sure that "[a-zA-Z0-9.()=|%/]+($|;)" match *all* allowed characters in cookies
			tmp =  document.cookie.match((new RegExp(key +'=[a-zA-Z0-9.()=|%/]+($|;)','g')));
			if(!tmp || !tmp[0]) return null;
			else return unescape(tmp[0].substring(key.length+1,tmp[0].length).replace(';','')) || null;
			
		},	
		
		/** Set a cookie
		 *
		 *  @param integer	key		The token that will be used to retrieve the cookie
		 *  @param string	value	The string to be stored
		 *  @param integer	ttl		Time To Live (hours)
		 *  @param string	path	Path in which the cookie is effective, default is "/" (optional)
		 *  @param string	domain	Domain where the cookie is effective, default is window.location.hostname (optional)
		 *  @param boolean 	secure	Use SSL or not, default false (optional)
		 * 
		 *  @return setted cookie
		 */
		set: function(key, value, ttl, path, domain, secure) {
			cookie = [key+'='+    escape(value),
					  'path='+    ((!path   || path=='')  ? '/' : path),
					  'domain='+  ((!domain || domain=='')?  window.location.hostname : domain)];
			
			if (ttl)         cookie.push(Mo.Cookie.hoursToExpireDate(ttl));
			if (secure)      cookie.push('secure');
			return document.cookie = cookie.join('; ');
		},
		
		/** Unset a cookie
		 *
		 *  @param integer	key		The token that will be used to retrieve the cookie
		 *  @param string	path	Path used to create the cookie (optional)
		 *  @param string	domain	Domain used to create the cookie, default is null (optional)
		 *  @return void
		 */
		unset: function(key, path, domain) {
			path   = (!path   || typeof path   != 'string') ? '' : path;
			domain = (!domain || typeof domain != 'string') ? '' : domain;
			if (Mo.Cookie.get(key)) Mo.Cookie.set(key, '', 'Thu, 01-Jan-70 00:00:01 GMT', path, domain);
		},
	
		/** Return GTM date string of "now" + time to live
		 *
		 *  @param integer	ttl		Time To Live (hours)
		 *  @return string
		 */
		hoursToExpireDate: function(ttl) {
			if (parseInt(ttl) == 'NaN' ) return '';
			else {
				now = new Date();
				now.setTime(now.getTime() + (parseInt(ttl) * 60 * 60 * 1000));
				return now.toGMTString();			
			}
		},
	
		/** Return true if cookie functionnalities are available
		 *
		 *  @return boolean
		 */
		test: function() {
			Mo.Cookie.set('b49f729efde9b2578ea9f00563d06e57', 'true');
			if (Mo.Cookie.get('b49f729efde9b2578ea9f00563d06e57') == 'true') {
				Mo.Cookie.unset('b49f729efde9b2578ea9f00563d06e57');
				return true;
			}
			return false;
		},
		
		/** If Firebug JavaScript console is present, it will dump cookie string to console.
		 * 
		 *  @return void
		 */
		dump: function() {
			if (typeof console != 'undefined') {
				console.log(document.cookie.split(';'));
			}
		},
		
		//删除所有 cookies
		clear : function (){
			var keys=document.cookie.match(/[^ =;]+(?=\=)/g);
			
			//alert( keys );
			
			if (keys) {
				for (var i = keys.length; i--;){
					//document.cookie = keys[i]+'=0;expires=' + new Date(0).toUTCString();
					
					Mo.Cookie.unset( keys[i] );					
				}
			}
		} 
		
	}
	
	
	/*
		获取URL参数
		key	参数名称
		url		URL链接，默认为当前URL
	*/
	Mo.get = function( key , url ){
		
		var url = url ? url : location.href;	
		var v = '';
		var o = url.indexOf( key + "=" );
		if (o != -1){
			o += key.length + 1 ;
			e = url.indexOf("&", o);
			if (e == -1){
				e = url.length;
			}
			//v = decodeURIComponent(url.substring(o, e));
			v = url.substring(o, e);
		}

		return v;
	}
	
	/*
		加载 Script 脚本
		src		文件地址
		charset	编码
		target	目标元素，默认为<head>
	*/
	Mo.script = function( src , charset , target ){
		
		//容器
		var target = target ? target : document.getElementsByTagName("HEAD")[0];
	
		var script  = document.createElement("script");
			script.type	= "text/javascript";
			script.src = src;
			script.charset = charset ? charset : "" ;
	
		target.appendChild(script);
	}
	
	/*
	
	
	importJs : function(url, onComplete, charset) {
		// 取得头部节点的引用
		var script = document.createElement("script");
		// 设置节点属性
		script.src = url; script.language = "javascript"; script.type = "text/javascript";
		if (charset) {
			script.charset = charset;
		}

		// 设定读取完以后的操作
		script.onload = script.onreadystatechange = function() {
			if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") {
				onComplete && onComplete(this);
				script.onload = script.onreadystatechange = null;
				this.parentNode.removeChild(script);
			}
		};
		head.appendChild(script);
	}

	
	*/

	
	/*
		Ajax
		file	文件名称
	*/
	Mo.Ajax = function(file) {
		this.xmlhttp = null;
	
		this.resetData = function() {
			this.method = "GET";
			this.URLString = "";
			this.encodeURL = true;
			this.file = file;
			this.late = true;
			this.failed = false;
		};
	
		this.resetFunctions = function() {
			this.onLoading = function() { };
			this.onLoaded = function() { };
			this.onInteractive = function() { };
			this.onCompletion = function() { };
			this.onError = function() { };
			this.encode = (encodeURIComponent && this.encodeURL)?function(s) {
				return encodeURIComponent(s);
			}:function(s){return s;}
		};
	
		this.reset = function() {
			this.resetFunctions();
			this.resetData();
		};
	
		this.createAJAX = function(){
			try {
				this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
			}catch (e1){
				try {
					this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e2) {
					this.xmlhttp = null;
				}
			}
			if (! this.xmlhttp) {
				if (typeof XMLHttpRequest != "undefined") {
					this.xmlhttp = new XMLHttpRequest();
				} else {
					this.failed = true;
				}
			}
		};
	
		this.setVar = function(name, value) {
			var arr1 = [], arr2 = [];
			if (typeof name == "object" && !value) {
				for(var i in name) {
					arr1[arr1.length] = i;
					arr2[arr2.length] = name[i];
				}
			}
			else {
				arr1[0] = name;
				arr2[0] = value;
			}
			var first = (this.URLString.length == 0);
			for(var i=0;i<arr1.length;i++) {
				this.URLString += (first)?"":"&";
				this.URLString += arr1[i] + "=" + this.encode(arr2[i]);
			}
		};
	
		/*
			返回最终请求地址
		*/
		this.getURL = function(){
			return this.file+"?"+this.URLString;		
		}
	
		this.send = function(content) {
			if (!content) content = "";
			if (!this.xmlhttp || this.failed ) {
				this.onError();
				return;
			}
			var self = this;
			if (this.method == "GET" || this.method == "GET&POST") {
				this.xmlhttp.open(this.method,this.file+"?"+this.URLString,this.late);
			} else if (this.method == "POST") {
				this.xmlhttp.open(this.method,this.file,this.late);
				try {
					this.xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
				} catch(e) {}
			}
			else this.onError();
	
			this.xmlhttp.onreadystatechange = function() {
				switch (self.xmlhttp.readyState) {
					case 1:
						self.onLoading();
						break;
					case 2:
						self.onLoaded();
						break;
					case 3:
						self.onInteractive();
						break;
					case 4:
						self.response = self.xmlhttp.responseText;					
						self.responseXML = self.xmlhttp.responseXML;
						try{
							var status = self.xmlhttp.status;
						}catch(e){
							var status = "Trouble accessing it";
						}
	
						if (self.xmlhttp.readyState == 4 || status == "200") {
							self.onCompletion();
						} else {
							self.onError();
						}
						self.URLString = "";
						break;
				}
			};
	
			if (this.method == "POST") {
				this.xmlhttp.send(this.URLString);
			} else if (this.method == "GET") {
				this.xmlhttp.send(null);
			} else if (this.method == "GET&POST") {
				this.xmlhttp.send(content);
			}
		};
	
		this.reset();
		this.createAJAX();
	}
	
	/********* 拖动对象_开始 *********/
	
	Mo.Drag = function( a ){
		
		var self = this;
	
		this.obj = null;
	
		/*	
		o ：是想现实鼠标拖动的组件；
		oRoot ： 是o上层的组件，将随o一起拖动；
		minX, maxX, minY, maxY ：设置鼠标拖动的范围，由下面的例子cropper可以看出，如果有oRoot,那范围是由oRoot相对于页面来说的；
		bSwapHorzRef, bSwapVertRef ：设置组件的优先权；
		fXMapper, fYMapper： 设置拖动的路径	
		*/	
		
		/* api 说明：
		*     方法调用可以参考：http://www.dynamicdrive.com/dynamicindex11/domdrag/
		*         o 拖拽 Handle
		*        oRoot 被拖拽 element  (可选, 默认不填 o为被拖拽对象  type=object)
		*        minX, maxX, minY, maxY 限制拖拽范围 (可选,默认不填为全屏 type=int )
		*         bSwapHorzRef, bSwapVertRef 判断是否允许 横，纵向拖拽(可选,默认不填无限制 type=boolean )
		*     fXMapper(x), fYMapper(y)  为外置函数 拖拽效果体现前调用 (x,y) 为当前element位置(可选 type=Function）
		*/  
		this.init = function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper){
			
			//alert(o.tagName);
		
			 /* 拖拽事件 挂载  (本js 主线 生命周期 描述)
			 *    1. 预定 o.onmousedown事件触发运行  Drag.start。
			 *    2. 触发 element-> onmousedown->Drag.start
			 *        2.1    先得到 element 当前"改变初"位置,记入到 o.lastMouseX ;o.lastMouseY，挂载Drag.obj,Darp.root 为当前 element。
			 *        2.2     预定 document.onmousemove    = Drag.drag; document.onmouseup = Drag.end。
			 *    3.  触发 document.onmousemove 运行 Drag.drag-> 拖拽效果体现。
			 *    4.  触发 document.onmouseup 运行 Drag.end-> 挂载 document.onmousemove;document.onmouseup;Drag.obj取消。
			 */
			o.onmousedown	= self.start;
	
			//是否能 横，纵向拖拽 
			o.hmode			= bSwapHorzRef ? false : true ;
			o.vmode			= bSwapVertRef ? false : true ;
	
			//挂载 o.root 
			o.root = oRoot && oRoot != null ? oRoot : o ;
	
			if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
			if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
			if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
			if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
	
			// 限定 移动范围 
			o.minX	= typeof minX != 'undefined' ? minX : null;
			o.minY	= typeof minY != 'undefined' ? minY : null;
			o.maxX	= typeof maxX != 'undefined' ? maxX : null;
			o.maxY	= typeof maxY != 'undefined' ? maxY : null;
	
			o.xMapper = fXMapper ? fXMapper : null;
			o.yMapper = fYMapper ? fYMapper : null;
			
			/*自定义拖拽－事件添加（相当于我们在java中的 抽象类 中未实现的方法  比如：
			*    obj.onDrag = function(x, y) {
			*        scrolldiv.style.top=y * (-1) +"px";
			*    }
			*/  
			self.onDragStart	= new Function();
			self.onDragEnd	= new Function();
			self.onDrag		= new Function();			
			
			//禁用右键菜单(by denglq) 
			//document.oncontextmenu = function(e){return false};
		}
	
		//由 function init >> o.onmousedown    = Drag.start; 
		this.start = function(e){
		
			//判断是否为鼠标右键点击，不是的话不触发拖拽操作(by denglq)
			//if (event.button != 2) {
			//	return false;
			//}
		
			//得到被拖拽 element 
			//var o = self.obj = this;
			var o = self.obj = this;
			e = self.fixE(e);
			
			//element 移动初位置
			var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
			var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
			
			//可能的外置函数调用，传入 this ( by Lay)
			//self.onDragStart(x, y);
			self.onDragStart.call( o.root , x, y);
			
	
			//event 初位置 记入 
			o.lastMouseX	= e.clientX;
			o.lastMouseY	= e.clientY;
	
			if (o.hmode) {
				if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
				if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
			} else {
				if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
				if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
			}
	
			if (o.vmode) {
				if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
				if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
			} else {
				if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
				if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
			}
	
			/*>>>>>>>>>>>比较关键的挂载<<<<<<<<<<<<<<
			*
			*    使用 document.onmousemove 事件 而不使用 element的，是应为当拖动太快，可能会脱离element.
			*/ 
			document.onmousemove	= self.drag;
			document.onmouseup		= self.end;
	
			return false;
		}
	
		//由 function start>> document.onmousemove    = Drag.drag; 
		this.drag = function(e){
			e = self.fixE(e);
			var o = self.obj;
	
			var ey	= e.clientY;
			var ex	= e.clientX;
			
			//得到 element 当前位置（vmode,hmode判断是否可以横纵向拖拽）
			var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
			var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
			var nx, ny;
	
			if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
			if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
			if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
			if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);
	
			//本js中 最主要的地方：
			//得到 鼠标移动 向量 drap(x,y) = fun_drap:event(x,y) - fun_start:event(x,y)
			//并于 得到拖拽效果:  element(x,y) + drap(x,y)  
			nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
			ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
	
			if (o.xMapper){
				nx = o.xMapper(y)
			}else if (o.yMapper){
				ny = o.yMapper(x)
			}
	
			//效果体现
			self.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
			self.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
			self.obj.lastMouseX	= ex;
			self.obj.lastMouseY	= ey;
	
			//调用外置函数，传入 this ( by Lay )
			//self.onDrag(nx, ny);
			self.onDrag.call( self.obj.root ,nx, ny);
			
			return false;
		}
	
		//结束拖动
		//由 function start>> document.onmouseup        = Drag.end;
		this.end = function(){
		
			document.onmousemove = null;
			document.onmouseup   = null;
			//document.oncontextmenu = null;
			
			//传入 this ( by Lay )
			//self.onDragEnd( parseInt(self.obj.root.style[self.obj.hmode ? "left" : "right"]), parseInt(self.obj.root.style[self.obj.vmode ? "top" : "bottom"]));
			self.onDragEnd.call( self.obj.root , parseInt(self.obj.root.style[self.obj.hmode ? "left" : "right"]), parseInt(self.obj.root.style[self.obj.vmode ? "top" : "bottom"]));
			
			self.obj = null;
		}
	
		//跨 浏览器 得到 event 
		this.fixE = function(e){
			if (typeof e == 'undefined') e = window.event;
			if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
			if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
			return e;
		}
		
		
		var arg = arguments;
		if( arg.length ){
			this.init( arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7], arg[8], arg[9]);
		}
		
	}
	
	/********* 拖动对象_结束 *********/
	
	/********* 数组对象扩展_开始 *********/
	
	Mo.Array = function( source ){	
	
		//内部类
		var inti = function( source ){
			this.self = source;
			return this;
		}

		//扩展方法
		inti.prototype = {
		
			//返回源
			output : function(){				
				return this.self;
			},
			
			//返回第一个元素
			first : function () {
				return this.self[0];
			},
			
			//返回最后一个元素
			last : function () {
				return this.self[this.self.length - 1];
			},
	
			//清空数组
			clear :function(){
				this.self = [];
				return this;
			},
	
			/*
				检查在数组内是否存在某值
				value	要查找的值
			*/
			indexOf : function( value ) {
				var l = this.self.length;
				for(var i=0; i<=l; i++) {
					if( this.self[i]== value ) return i;
				}
				return -1;
			}

		}

		//实例化类
		return new inti(source);
		
	}	
	
	/********* 数组对象扩展_结束 *********/
	

	/********* 字符串扩展_开始 *********/
	
	Mo.String = function( source ){
		
		//内部类
		var inti = function( source ){
			this.self = source;
			return this;
		}
		
		//扩展方法
		inti.prototype = {
		
			//返回源
			output : function(){				
				return this.self;
			},
			
			//返回字符串长度		*待修改
			long : function(){
				var str = this.self;
				var l = str.length;
				var len = 0;
				for (var i=0;i<l;i++){
					if (str.charCodeAt(i)>255){
						len+=2; 
					}else{ 
						len++;
					}
				}
				return len;
			},
					
			//去掉左右空白字符
			trim : function(str){
				this.self = this.self.replace(/(^\s*)|(\s*$)/g, "");
				return this;
			},
			
			//去掉左边空白字符
			leftTrim : function(str){
				this.self = this.self.replace(/(^\s*)/g, "");
				return this;
			},
			
			//去掉右边空白字符
			rightTrim : function(str){
				this.self = this.self.replace(/(\s*$)/g, "");
				return this;
			},
	
			//过滤JS
			stripScript : function(s) {
				this.self = this.self.replace(/<script.*?>.*?<\/script>/ig, '');
				return this;
			},
			
			//ASCII -> Unicode转换
			unicode : function(){
				
				if( this.self ){				
					var result = '';
					for (var i=0; i<this.self.length; i++){
						result += '&#' + this.self.charCodeAt(i) + ';';
					}					
					this.self = result;
					
					//alert(result);
				}
				
				return this;
			},
			
			//Unicode -> ASCII转换
			ascii : function() {
				
				if( this.self ){				
					var code = this.self.match(/&#(\d+);/g);					
					if( code != null ){					
						var result = '';
						for (var i=0; i<code.length; i++){
							result += String.fromCharCode(code[i].replace(/[&#;]/g, ''));
						}						
						this.self = result;					
					}				
				}
				
				return this;
			},
			
			//格式化字符串
			format : function (){
				var param = [];
				for (var i = 0, l = arguments.length; i < l; i++){
					param.push(arguments[i]);
					//alert(i);
				}
				
				//var statment = param[0]; // get the first element(the original statement)
				//param.shift(); // remove the first element from array
				
				this.self = this.self.replace(/\{(\d+)\}/g, function(m, n)
				{
					return param[n];
				});
				
				return this;
			}		
		}
	
		//实例化类
		return new inti(source);
	}
	
	/********* 字符串扩展_结束 *********/

	/********* 数值扩展_开始 /*********/

	Mo.Number ={

		//将数字补前置零
		test : function(){
			alert('');
			return ;
		},

		test2 : function(){
			alert('');
			return ;
		},
		
		/* 检查是否全为数字 */
		isNumber : function(num){
			return /^[0-9]{1,20}$/.exec(num);
		}
		
	}	

	/********* 数值扩展_结束 *********/

	/********* 函数扩展_开始 *********/

	Mo.Function ={

		test:function(){
			alert('');
			return ;
		},

		test2:function(){
			alert('');
			return ;
		}	
	}	

	/********* 函数扩展_结束 *********/
	
	
	/********* 日期扩展_开始 *********/

	Mo.Date ={

		test:function(){
			alert('');
			return ;
		},

		test2:function(){
			alert('');
			return ;
		}	
	}	

	/********* 日期扩展_结束 *********/
	
	/********* 事件扩展_开始 *********/

	Mo.Event = function(){
	
	
		//内部类
		var inti = function( source ){
			this.self = source;
			return this;
		}

		//扩展方法
		inti.prototype = {
		
			//返回源
			output : function(){				
				return this.self;
			},
			
			//返回第一个元素
			first : function () {
				return this.self[0];
			},
			
			//返回最后一个元素
			last : function () {
				return this.self[this.self.length - 1];
			},
	
			//清空数组
			clear :function(){
				this.self = [];
				return this;
			},
	
			/*
				检查在数组内是否存在某值
				value	要查找的值
			*/
			indexOf : function( value ) {
				var l = this.self.length;
				for(var i=0; i<=l; i++) {
					if( this.self[i]== value ) return i;
				}
				return -1;
			}

		}

		//实例化类
		return new inti(source);
		
	
	/////////////////////////////////

		/*停止事件冒泡*/
		stop:function(e){
			var e = e || window.event;
			if ( Mo.Browser.msie ) {
			
				//停止冒泡
				e.cancelBubble = true;

				//阻止浏览器默认动作
				e.returnValue = false;
				
			} else {
				
				//停止冒泡
				e.stopPropagation();
				
				//阻止浏览器默认动作(W3C)
				e.preventDefault();

			}
			
			return false;
		},
		
		/* 发生事件的节点 */
		getElement : function(e) {
			if ( Mo.Browser.msie ) {
				return window.event.srcElement;
			}else{
				return e.currentTarget;
			}
		},
		
		/* 发生当前在处理的事件的节点 */
		getTargetElement : function(e) {
			if ( Mo.Browser.msie ) {
				return window.event.srcElement;
			}else{
				return e.target;
			}
		},
		
		/* 鼠标位置 */
		getMouse:function(e){
			if ( Mo.Browser.msie ) {
				var x = e.x + VeryIDE.getDocument().scrollLeft;
				var y = e.y + VeryIDE.getDocument().scrollTop;
			}else{
				var x = e.pageX;
				var y = e.pageY;
			}
			return { "x":x, "y":y };
		}
		
	}

	/********* 事件扩展_结束 *********/		

	
	/********* 验证函数_开始 *********/
	
	Mo.Validate ={
	
		//判断对象是否是数组
		isArray : function(obj){
			return Object.prototype.toString.apply(obj) === '[object Array]';
		},
	
		//判断对象是否是函数
		isFunction : function(obj){
			return Object.prototype.toString.apply(obj) === '[object Function]';
		},
	
		//判断对象是否是元素
		/*
		Mo.isElement = function(obj){
			return Object.prototype.toString.apply(obj) === '[object HTMLCollection]';
		}
		*/
	
		//判断对象是否是对象
		isObject : function(obj){
			return Object.prototype.toString.apply(obj) === '[object Object]';
		},
	
	
		//判断对象是否是数值
		/*
		Mo.isNumber = function(obj){
			return Object.prototype.toString.apply(obj) === '[object Number]';
		}
		*/
	
		//日期
		isDate : function(o){
			return Object.prototype.toString.apply(o) === '[object Date]';
		},
	
		//数值
		isNumber : function(o) {
			return typeof o === 'number' && isFinite(o);
		},
		
		//字符串
		isString : function(o){
			return typeof o === 'string';
		},
	
		//未定义
		isDefined : function(o){
			return typeof o != 'undefined';
		},
	
		//对象是否为空
		isEmpty : function(o){
			return typeof o == 'undefined' || o == '' ;
		},
	
		//布尔
		isBoolean : function(o){
			return typeof o === 'boolean';
		},

		//是否为Window对象
		isWindow : function(o){			
			return /\[object Window\]/.test( o );
		},

		//是否为HTML根
		isDocument : function(o){
			return /\[object HTMLDocument\]/.test( o );
		},
				
		//是否为HTML元素
		isElement : function(o){
			//alert(o);
			//return /\[object HTML\w*(Element)?\]/.test(Object.prototype.toString.apply(o));
			//return /\[object HTML\w*(Element)?\]/.test( o );
			//o.nodeType !=1 && 
			return o.tagName;
		},
	
		//是否为XML
		/*
		isXML : function(o){
			return  Object.prototype.toString.apply(o)==='[object XML]';
		},
		*/
		
		/****************************/

		//检查是否包含中文
		inChinese : function(str) { 
		  return (str.length != str.replace(/[^\x00-\xff]/g,"**").length); 
		},
		
		//检查是否为中文	*
		isInChinese : function(str) { 
		  return (str.length != str.replace(/[^\x00-\xff]/g,"**").length); 
		},
		
		//检查是否含有特殊字符
		isSafe : function(str){
			var chkstr;
			var i;
			chkstr="'*%_@#^$`~!^&*()=+{}\\|{}[];:/?<>,.";
			for (i=0;i<str.length;i++){
				if (chkstr.indexOf(str.charAt(i))!=-1) return false;
			}
			return true;
		},

		//检查是否为电子邮件地址
		isEmail : function(str){			
			return /^\s*([A-Za-z0-9_-]+(\.\w+)*@(\w+\.)+\w{2,3})\s*$/.test(str);
		},
		
		//检查是否为URL地址
		isURL : function(str){			
			return /^[a-zA-z]+:\/\/(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$/.test(str);
		},

		//检查是否为合法IP
		isIP : function(str){
			return /^[0-9.]{1,20}$/.test(str);
		},

		//检查是否为合法密码
		isPassword : function(str){
			return /^(\w){6,20}$/.test(str);
		},
		
		//检查是否为颜色值
		isColor : function(str){
			return /^#(\w){6}$/.test(str);
		}
		
	}	
	
	/********* 验证函数_结束 *********/

	/********* 调试助手_开始 *********/

	Mo.Logs = {
	
		//容器
		box:null,

		//初始化，注册容器
		start:function(obj){
			Mo.Logs.box = document.getElementById(obj);
		},

		//清空调试信息
		clear:function(){
			if( Mo.Logs.box ) Mo.Logs.box.innerHTML = '';
		},
		
		//正常
		debug:function(str){
			if( Mo.Logs.box ) Mo.Logs.box.innerHTML = '&#12304;&#8730;&#12305;'+ str + '<br />' +Mo.Logs.box.innerHTML;
		},

		//消息
		point:function(str){
			if( Mo.Logs.box ) Mo.Logs.box.innerHTML = '&#12304;&#9633;&#12305;'+ str + '<br />' +Mo.Logs.box.innerHTML;
		},
		
		//警告
		alert:function(str){
			if( Mo.Logs.box ) Mo.Logs.box.innerHTML = '&#12304;&#9679;&#12305;'+ str + '<br />' +Mo.Logs.box.innerHTML;
		},
		
		//错误
		error:function(str){
			if( Mo.Logs.box ) Mo.Logs.box.innerHTML = '&#12304;&#215;&#12305;'+ str + '<br />' +Mo.Logs.box.innerHTML;
		}
		
	}	
	
	
	/**
	 * "mini" Selector Engine
	 * Copyright (c) 2009 James Padolsey
	 * -------------------------------------------------------
	 * Dual licensed under the MIT and GPL licenses.
	 *    - http://www.opensource.org/licenses/mit-license.php
	 *    - http://www.gnu.org/copyleft/gpl.html
	 * -------------------------------------------------------
	 * Version: 0.01 (BETA)
	 */
	 
	/*	
	tag
	tag > .className
	tag > tag
	#id > tag.className
	.className tag
	tag, tag, #id
	tag#id.className
	.className
	span > * > b	
	*/
	Mo.find = (function(){
		
		var snack = /(?:[\w\-\\.#]+)+(?:\[\w+?=([\'"])?(?:\\\1|.)+?\1\])?|\*|>/ig,
			exprClassName = /^(?:[\w\-_]+)?\.([\w\-_]+)/,
			exprId = /^(?:[\w\-_]+)?#([\w\-_]+)/,
			exprNodeName = /^([\w\*\-_]+)/,
			na = [null,null];
		
		function _find(selector, context) {
			
			/**
			 * This is what you call via x()
			 * Starts everything off...
			 */
			context = context || document;
			
			var simple = /^[\w\-_#]+$/.test(selector);
			
			if (!simple && context.querySelectorAll) {
				return realArray(context.querySelectorAll(selector));
			}
			
			if (selector.indexOf(',') > -1) {
				var split = selector.split(/,/g), ret = [], sIndex = 0, len = split.length;
				for(; sIndex < len; ++sIndex) {
					ret = ret.concat( _find(split[sIndex], context) );
				}
				return unique(ret);
			}
			
			var parts = selector.match(snack),
				part = parts.pop(),
				id = (part.match(exprId) || na)[1],
				className = !id && (part.match(exprClassName) || na)[1],
				nodeName = !id && (part.match(exprNodeName) || na)[1],
				collection;
				
			if (className && !nodeName && context.getElementsByClassName) {				
				collection = realArray(context.getElementsByClassName(className));				
			} else {
				
				collection = !id && realArray(context.getElementsByTagName(nodeName || '*'));
				
				if (className) {
					collection = filterByAttr(collection, 'className', RegExp('(^|\\s)' + className + '(\\s|$)'));
				}
				
				if (id) {
					var byId = context.getElementById(id);
					return byId?[byId]:[];
				}
			}
			
			return parts[0] && collection[0] ? filterParents(parts, collection) : collection;
			
		}
		
		function realArray(c) {
			
			/**
			 * Transforms a node collection into
			 * a real array
			 */
			try {
				return Array.prototype.slice.call(c);
			} catch(e) {
				var ret = [], i = 0, len = c.length;
				for (; i < len; ++i) {
					ret[i] = c[i];
				}
				return ret;
			}
			
		}
		
		function filterParents(selectorParts, collection, direct) {
			
			/**
			 * This is where the magic happens.
			 * Parents are stepped through (upwards) to
			 * see if they comply with the selector.
			 */
			var parentSelector = selectorParts.pop();
			
			if (parentSelector === '>') {
				return filterParents(selectorParts, collection, true);
			}
			
			var ret = [],
				r = -1,
				id = (parentSelector.match(exprId) || na)[1],
				className = !id && (parentSelector.match(exprClassName) || na)[1],
				nodeName = !id && (parentSelector.match(exprNodeName) || na)[1],
				cIndex = -1,
				node, parent,
				matches;
				
			nodeName = nodeName && nodeName.toLowerCase();
				
			while ( (node = collection[++cIndex]) ) {
				
				parent = node.parentNode;
				
				do {
					
					matches = !nodeName || nodeName === '*' || nodeName === parent.nodeName.toLowerCase();
					matches = matches && (!id || parent.id === id);
					matches = matches && (!className || RegExp('(^|\\s)' + className + '(\\s|$)').test(parent.className));
					
					if (direct || matches) { break; }
					
				} while ( (parent = parent.parentNode) );
				
				if (matches) {
					ret[++r] = node;
				}
			}
			
			return selectorParts[0] && ret[0] ? filterParents(selectorParts, ret) : ret;
			
		}
		
		
		var unique = (function(){
			
			var uid = +new Date();
					
			var data = (function(){
			 
				var n = 1;			 
				return function(elem) {
			 
					var cacheIndex = elem[uid],
						nextCacheIndex = n++;
			 
					if(!cacheIndex) {
						elem[uid] = nextCacheIndex;
						return true;
					}
			 
					return false;
			 
				};
			 
			})();
			
			return function(arr) {
			
				/**
				 * Returns a unique array
				 */
				var length = arr.length,
					ret = [],
					r = -1,
					i = 0,
					item;
					
				for (; i < length; ++i) {
					item = arr[i];
					if (data(item)) {
						ret[++r] = item;
					}
				}
				
				uid += 1;
				
				return ret;
		
			};
		
		})();
		
		function filterByAttr(collection, attr, regex) {
			
			/**
			 * Filters a collection by an attribute.
			 */
			var i = -1, node, r = -1, ret = [];
			
			while ( (node = collection[++i]) ) {
				if (regex.test(node[attr])) {
					ret[++r] = node;
				}
			}
			
			return ret;
		}
		
		return _find;
		
	})();


	/********* 调试助手_结束 *********/
	
	/*
		扩展函数
		
		func	函数
	*/
	Mo.extend = function( func ){
	
		for( var i in func){
			
			Mo.init.prototype[i] = func[i];
			
		}
		
	}
	
	/*
		初始化
		
		selector	选择器
		context		父对象
	*/
	Mo.init = function( selector, context){
	
		//选中对象
		//this.self = document.getElementById(obj);
		
		this.self = Mo.Validate.isElement( selector ) || Mo.Validate.isDocument( selector ) || Mo.Validate.isWindow( selector ) ? [selector] : Mo.find( selector, context );
		
		//this.self = Mo.find( selector, context );
		
	}

	Mo.init.prototype = {

		/*
			校验元素
			
			返回：
			true	对象存在
			false	对象不存在
		*/
		verify : function(){			
			return this.self.length > 0 ? true :false ;			
		},

		/*
			元素数量
			
			返回：
			int		数量
		*/
		size : function(){			
			return this.self.length;			
		},

		/*
			选择元素
			
			返回：
			int		数量
		*/
		choice : function( i ){			
			return i <= this.self.length ? this.self[i] : null;			
		},

		/*
			隐藏元素
			speed	速度
			func	回调函数
		*/
		hide : function(speed,func){
			
			//批量绑定
			this.foreach( function( ele ){
					
				ele.style.display = "none";
				
				if( typeof(func) == "function" ) func( ele );
				
			} );

			return this;
		},
		
		/*
			显示元素
			speed	速度
			func	回调函数
		*/
		show : function( speed,func ){
			
			//批量绑定
			this.foreach( function( ele ){
					
				ele.style.display = "";
				
				if( typeof(func) == "function" ) func( ele );
				
			} );

			return this;
		},
		
		/*
			显示或隐藏对象
			speed	速度
			func	回调函数
		*/
		toggle : function(speed,func){
		
			//批量绑定
			this.foreach( function( ele ){

				if(ele.offsetHeight == 0 || ele.offsetWidth == 0) {
					ele.style.display = "block";
					var res = true;
				}else{
					ele.style.display = "none";
					var res = false;
				}

			} );
		
			//回调函数
			if( typeof(func) == "function" ) func( res );
	
			return this;
		},

		/*
			设置或返回对象值
			text	[可选]文本值
		*/	
		value : function( text ){
		
			//设置值
			if( typeof text != "undefined" ){
		
				//批量绑定
				this.foreach( function( ele ){
					
					//子元素数量
					var len = ele.length;
					
					//按类型处理
					switch( ele.type ){
						
						//单选下拉
						case "select-one":							
							
							for(var i=0;i<len;i++){
								if( ele[i].value == text ){
									ele.selectedIndex=i;
									break;
								}
							}
							
						break;
						
						//多选下拉
						case "select-multiple":
							
							for(var i=0;i<len;i++){
								if( Mo.Array( text ).indexOf( ele[i].value ) !== -1 ){
									ele[i].selected = true;
								}else{
									ele[i].selected = false;
								}
							}
							
						break;
						
						//单选和筛选按钮
						case "radio":
						case "checkbox":
								
							if(ele.value == text){
								ele.checked=true;
							}else{
								ele.checked=false;
							}
							
						break;
						
						//文本框、隐藏域和多行文本
						case "text"	:
						case "hidden":
						case "textarea":
						case "password":
							ele.value = text;
						break;
						
					}
					
				} );
			
				return this;
				
			}
			
			///////////////////////////////////
			
			//返回值
			var val = [];
			
			//批量绑定
			this.foreach( function( ele ){
			
				//子元素数量
				var len = ele.length;
				
				//按类型处理
				switch( ele.type ){
			
					//单选下拉
					case "select-one":
						
						if( len ){
							val = ele[ele.selectedIndex].value;
						}
						
					break;
					
					//多选下拉
					case "select-multiple":
						
						for(var i=0;i<len;i++){								
							if( ele[i].selected ){
								val.push(ele[i].value);
							}
						}
						
					break;
					
					//单选和筛选按钮
					case "radio":
					case "checkbox":

						/*
						for(var i=0;i<len;i++){
							if( ele[i].checked ){
								val.push(ele[i].value);
							}
						}
						*/
						
						//for(var i=0;i<len;i++){
							if( ele.checked ){
								val.push(ele.value);
							}
												
						
					break;
					
					//文本框、隐藏域和多行文本
					case "text"	:
					case "hidden":
					case "textarea":					
					case "password":					
						val = ele.value;						
					break;
				
				}
				
			} );
		
			return val;
		},
		
		/*
			设置或返回对象内容
			html	[可选]代码块
		*/	
		html : function( html ){
			
			if( typeof html != "undefined" ){
			
				//批量绑定
				this.foreach( function( ele ){			
					ele.innerHTML = html;				
				} );
				
				return this;
			}
			
			var ele = this.self[0];
			
			return ele.innerHTML;
		},
		
		/*
			设置或返回对象样式名
			key		[必选]属性名称
			val		[可选]属性值
		*/	
		attr : function( key , val ){
		
			//写入值
			if( typeof val != "undefined" ){
			
				//批量绑定
				this.foreach( function( ele ){
						
						switch( key ){
						
							case "class":
								ele.className = val;
							break;
							
							default:
								ele.setAttribute(key,val);					
							break;
							
						}
					
				} );
				
				return this;
				
			}
			
			var ele = this.self[0];
			
			//读取值
			switch( key ){
			
				case "class":
					return ele.className;
				break;
				
				default:
					return ele.getAttribute(key);					
				break;
				
			}		
			
		},

		/*
			设置或返回对象样式
			key		String 时返回样式值
						JSON	时设置样式，如：{"color":"red","fontSize":"14px"}
			
		*/
		style : function( key ){
		
			//返回对象样式
			if( typeof key == "string" ){
			
				var ele = this.self[0];
			
				//如果该属性存在于style[]中，则它最近被设置过(且就是当前的)    
				if (ele.style[key]){						
					return ele.style[key];    
				}    
				//否则，尝试IE的方式    
				else if (ele.currentStyle){				
					return ele.currentStyle[key];    
				}    
				//或者W3C的方法，如果存在的话    
				else if (document.defaultView && document.defaultView.getComputedStyle){    
					//它使用传统的"text-Align"风格的规则书写方式，而不是"textAlign"    
					key = key.replace(/([A-Z])/g,"-$1");    
					key = key.toLowerCase();    
					//获取style对象并取得属性的值(如果存在的话)    
					var s = document.defaultView.getComputedStyle(ele,"");
					
					return s && s.getPropertyValue(key);    
				//否则，就是在使用其它的浏览器    
				}else{    
					return null;    
				} 
			
			}else{
			
				//批量绑定
				this.foreach( function( ele ){
					
					//设置对象样式
					for(var x in key){
						ele.style[x] = key[x];
					}
					
				} );
				
				return this;
			
			}
			
		},
		
		/*
			返回对象位置和尺寸信息
			json	如：{"width":width,"height":height}
		*/
		position : function( json ){
			
			var ele = this.self[0];
			
			var width 	= ele.offsetWidth;
			var height	= ele.offsetHeight;
			
			var top		= ele.offsetTop;
			var left	= ele.offsetLeft;
			
			while( ele = ele.offsetParent ){
				top 	+= ele.offsetTop;
				left	+= ele.offsetLeft;
			}
			
			return {"width":width, "height":height, "top":top, "left":left};
			
		},
		
		/*
			遍历元素，执行批量操作
			func		需要执行的函数
		*/
		foreach : function( func ){
			
			var ele = this.self;
			
			for( var i = 0; i< ele.length; i++ ){
				
				/*
					回调参数
					ele[i]	当前元素
					i		当前索引	
				*/
				//func( ele[i] , i );
				
				func.call( ele[i] , ele[i] , i );
				
			}
			
			return this;
			
		},
		
		/*
			为对象绑定事件
			evt		事件名称
			func	要执行的函数	
		*/
		bind : function( evt , func ){
		
			//批量绑定
			this.foreach( function( ele , index ){
				
				var oldonevent = ele['on'+evt];
				
				//没有绑定
				if (typeof ele['on'+evt] != 'function') {					
					ele['on'+evt] = function(event){
						return func.call( ele , index , event );
					};					
				} else {					
					ele['on'+evt] = function(event) {
						oldonevent(event);
						return func.call( ele , index , event );
					}
				}				
				
			} );
			
			return this;
		},

		/*
			移除为对象绑定的事件
			evt		事件名称	
		*/
		unbind : function(evt){

			//批量绑定
			this.foreach( function( ele ){
				ele['on'+evt] = null;				
			} );

			return this;
		},
				
		/*
			设置对象焦点
			func	要执行的函数	
		*/
		focus : function( func ){
			
			//批量绑定
			this.foreach( function( ele , index ){
			
				//alert(ele);
				
				ele.focus();
				
				//回调
				if(typeof func == 'function'){				
					return func.call( ele , index );				
				}
				
			} );			
			
			return this;
		},
		
		/*
			使对象失去焦点
			func	要执行的函数	
		*/
		blur : function( func ){
			
			//批量绑定
			this.foreach( function( ele , index ){
				
				ele.blur();
				
				//回调
				if(typeof func == 'function'){				
					return func.call( ele , index );				
				}
				
			} );			
			
			return this;
		},

		/*
			禁用当前元素	
		*/		
		disabled : function(){
		
			//批量绑定
			this.foreach( function( ele ){					
				ele.disabled = true;				
			} );

			return this;
		},
		
		/*
			启用当前元素
		*/		
		enabled : function(){
		
			//批量绑定
			this.foreach( function( ele ){					
				ele.disabled = false;				
			} );

			return this;
		},

		/*
			创建元素
			obj		元素对象
			attr		属性对象
			self		是否返回当前元素
		*/
		create : function( tag , attr , self ){
		
			//创建对象
			var obj = document.createElement( tag);
			
			//附加属性
			if( attr ){
				for( var i in attr ){
					obj[i] = attr[i];
				}
			}
		
			//批量插入
			this.append( obj );
			
			if( self ) return obj;

			return this;
		},

		/*
			插入元素
			obj		元素对象
		*/
		append : function( obj ){		

			//批量插入
			this.foreach( function( ele ){					
				ele.appendChild(obj);			
			} );

			return this;
		},
		
		/*
			删除元素
		*/
		remove : function(){		

			//批量删除
			this.foreach( function( ele ){					
				ele.parentNode.removeChild(ele);			
			} );

			return this;
		},
		
		//animation api
		animation : function(obj, left, top, width, height, time, callbackFun) {
			if (!obj) return;
			var interval = 10;
			time = (time && time > 100 ? time : 100) / interval;
			var step = [
				  parseInt((left != null ? parseInt(left) - parseInt(obj.offsetLeft) : 0) / time)
				, parseInt((top != null ? parseInt(top) - parseInt(obj.offsetTop) : 0) / time)
				, parseInt((width != null ? parseInt(width) - parseInt(obj.offsetWidth) : 0) / time)
				, parseInt((height != null ? parseInt(height) - parseInt(obj.offsetHeight) : 0) / time)
			];
			var t = 0;
			var timer = setInterval(function(){
				if (++t > time) {
					clearInterval(timer);
					if (callbackFun) callbackFun();
					return ;
				}
	
				obj.style.left = parseInt(obj.offsetLeft) + parseInt(step[0])+"px";
				obj.style.top = parseInt(obj.offsetTop) + parseInt(step [1])+"px";
				obj.style.width = parseInt(obj.offsetWidth) + parseInt(step[2])+"px";
				obj.style.height = parseInt(obj.offsetHeight) + parseInt(step[3])+"px";
			}, interval);
			
			return this;
		},

		
		/*
			动画效果
		*/
		motion : function( speed,option ){
		
			/*
				框架自身
			*/			
			Mo.Logs.start("logs");
			
			for( var o in option ){
			
				//alert(o);
			
				//修正参数
				var pos = this.position();
				if( !option[o].min && !option[o].max ) return this;
				if( !option[o].min ) option[o].min = pos[o];
				if( !option[o].max ) option[o].max = pos[o];				
				
				//对象起始状态
				if( option[o].min && option[o].min != pos[o] ){
					//Mo.Logs.info( option[o].min );					
					this.self.style[o] = option[o].min + "px";
				}
				
				var self = this;
				//var option = option;
				//var o = o;
				
				(function(){
				
					//alert( o );
					
					var x = o;
					var config = option;
				
					//var o = o;
					//var option = option;
					var root = self;
					
					//动画
					var rnd = Mo.random(10,true);
	
					Mo.temp[rnd] = setInterval(function(){						
	
						var pos = root.position();
						var val = config[x].max && pos[x] + speed > config[x].max ? config[x].max : pos[x] + speed;
	
						root.self.style[x] = val + "px";
						
						//Mo.Logs.debug( x + ' -- ' + val + '==' + config[o].max);
	
						if( val >= config[x].max  ){
							//alert(rnd);
							clearInterval( Mo.temp[rnd] );
							
							/*
							var s = "";
							for(var i in Mo.temp){
								s += i+ " - " + (typeof Mo.temp[i]) + " - " +",";
							}
							
							Mo.Logs.info( s );
							*/
						}
	
					}, 10 );
				})();
				
			}
			
			/*
			
			setInterval(function(){
			
				var pos = mo.position();
				
				mo.self.style.left = pos.left + 10 + "px";
				
			}, 10);
			*/
			
			return this;
		}

	}
	
	
	/*
		将字符串 base64 编码/解码
		string		源字符串
	*/
	Mo.base64 = function( string ){
	
		/* utf.js - UTF-8 <=> UTF-16 convertion
		*
		* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
		* Version: 1.0
		* LastModified: Dec 25 1999
		* This library is free.  You can redistribute it and/or modify it.
		*/
	
		/*
		* Interfaces:
		* utf8 = utf16to8(utf16);
		* utf16 = utf16to8(utf8);
		*/	
		function utf16to8(str) {
			var out, i, len, c;
	
			out = "";
			len = str.length;
			for(i = 0; i < len; i++) {
				c = str.charCodeAt(i);
				if ((c >= 0x0001) && (c <= 0x007F)) {
					out += str.charAt(i);
				} else if (c > 0x07FF) {
					out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
					out += String.fromCharCode(0x80 | ((c >>  6) & 0x3F));
					out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));
				} else {
					out += String.fromCharCode(0xC0 | ((c >>  6) & 0x1F));
					out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));
				}
			}
			return out;
		}
	
		function utf8to16(str) {
			var out, i, len, c;
			var char2, char3;
	
			out = "";
			len = str.length;
			i = 0;
			while(i < len) {
				c = str.charCodeAt(i++);
				switch(c >> 4)
				{
				  case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
					// 0xxxxxxx
					out += str.charAt(i-1);
					break;
				  case 12: case 13:
					// 110x xxxx   10xx xxxx
					char2 = str.charCodeAt(i++);
					out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
					break;
				  case 14:
					// 1110 xxxx  10xx xxxx  10xx xxxx
					char2 = str.charCodeAt(i++);
					char3 = str.charCodeAt(i++);
					out += String.fromCharCode(((c & 0x0F) << 12) |
												   ((char2 & 0x3F) << 6) |
												   ((char3 & 0x3F) << 0));
					break;
				}
			}
	
			return out;
		}
	
		/* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>
		* Version: 1.0
		* LastModified: Dec 25 1999
		* This library is free.  You can redistribute it and/or modify it.
		*/
	
		/*
		* Interfaces:
		* b64 = base64encode(data);
		* data = base64decode(b64);
		*/	
		var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		var base64DecodeChars = new Array(
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
			52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
			-1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
			15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
			-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
			41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
	
		function base64encode(str) {
			var out, i, len;
			var c1, c2, c3;
	
			len = str.length;
			i = 0;
			out = "";
			while(i < len) {
				c1 = str.charCodeAt(i++) & 0xff;
				if(i == len)
				{
					out += base64EncodeChars.charAt(c1 >> 2);
					out += base64EncodeChars.charAt((c1 & 0x3) << 4);
					out += "==";
					break;
				}
				c2 = str.charCodeAt(i++);
				if(i == len)
				{
					out += base64EncodeChars.charAt(c1 >> 2);
					out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
					out += base64EncodeChars.charAt((c2 & 0xF) << 2);
					out += "=";
					break;
				}
				c3 = str.charCodeAt(i++);
				out += base64EncodeChars.charAt(c1 >> 2);
				out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
				out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
				out += base64EncodeChars.charAt(c3 & 0x3F);
			}
			return out;
		}
	
		function base64decode(str) {
			var c1, c2, c3, c4;
			var i, len, out;
	
			len = str.length;
			i = 0;
			out = "";
			while(i < len) {
				/* c1 */
				do {
					c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
				} while(i < len && c1 == -1);
				if(c1 == -1)
					break;
	
				/* c2 */
				do {
					c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
				} while(i < len && c2 == -1);
				if(c2 == -1)
					break;
	
				out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
	
				/* c3 */
				do {
					c3 = str.charCodeAt(i++) & 0xff;
					if(c3 == 61)
						return out;
					c3 = base64DecodeChars[c3];
				} while(i < len && c3 == -1);
				if(c3 == -1)
					break;
	
				out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
	
				/* c4 */
				do {
					c4 = str.charCodeAt(i++) & 0xff;
					if(c4 == 61)
						return out;
					c4 = base64DecodeChars[c4];
				} while(i < len && c4 == -1);
				if(c4 == -1)
					break;
				out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
			}
			return out;
		}
	
		//input base64 encode
		function strdecode(str){
		   return utf8to16(base64decode(str));
		}
	
		//实例化
		this.encode = function(){
			return base64encode( string );
		}
		this.decode = function(){
			return base64decode( string );
		}
		
		return this;

	}
	
	/*
		将字符串 SHA1 加密
		string		源字符串
	*/
	Mo.sha1 = function(string){
		/*
		 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
		 * in FIPS PUB 180-1
		 * Version 2.1a Copyright Paul Johnston 2000 - 2002.
		 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
		 * Distributed under the BSD License
		 * See http://pajhome.org.uk/crypt/md5 for details.
		 */

		/*
		 * Configurable variables. You may need to tweak these to be compatible with
		 * the server-side, but the defaults work in most cases.
		 */
		var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
		var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
		var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

		/*
		 * These are the functions you'll usually want to call
		 * They take string arguments and return either hex or base-64 encoded strings
		 */
		function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
		function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
		function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
		function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
		function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
		function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}

		/*
		 * Perform a simple self-test to see if the VM is working
		 */
		function sha1_vm_test(){
		  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
		}

		/*
		 * Calculate the SHA-1 of an array of big-endian words, and a bit length
		 */
		function core_sha1(x, len){
		  /* append padding */
		  x[len >> 5] |= 0x80 << (24 - len % 32);
		  x[((len + 64 >> 9) << 4) + 15] = len;

		  var w = Array(80);
		  var a =  1732584193;
		  var b = -271733879;
		  var c = -1732584194;
		  var d =  271733878;
		  var e = -1009589776;

		  for(var i = 0; i < x.length; i += 16){
			var olda = a;
			var oldb = b;
			var oldc = c;
			var oldd = d;
			var olde = e;

			for(var j = 0; j < 80; j++){
			  if(j < 16) w[j] = x[i + j];
			  else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
			  var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
							   safe_add(safe_add(e, w[j]), sha1_kt(j)));
			  e = d;
			  d = c;
			  c = rol(b, 30);
			  b = a;
			  a = t;
			}

			a = safe_add(a, olda);
			b = safe_add(b, oldb);
			c = safe_add(c, oldc);
			d = safe_add(d, oldd);
			e = safe_add(e, olde);
		  }
		  return Array(a, b, c, d, e);

		}

		/*
		 * Perform the appropriate triplet combination function for the current
		 * iteration
		 */
		function sha1_ft(t, b, c, d){
		  if(t < 20) return (b & c) | ((~b) & d);
		  if(t < 40) return b ^ c ^ d;
		  if(t < 60) return (b & c) | (b & d) | (c & d);
		  return b ^ c ^ d;
		}

		/*
		 * Determine the appropriate additive constant for the current iteration
		 */
		function sha1_kt(t){
		  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
				 (t < 60) ? -1894007588 : -899497514;
		}

		/*
		 * Calculate the HMAC-SHA1 of a key and some data
		 */
		function core_hmac_sha1(key, data){
		  var bkey = str2binb(key);
		  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);

		  var ipad = Array(16), opad = Array(16);
		  for(var i = 0; i < 16; i++){
			ipad[i] = bkey[i] ^ 0x36363636;
			opad[i] = bkey[i] ^ 0x5C5C5C5C;
		  }

		  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
		  return core_sha1(opad.concat(hash), 512 + 160);
		}

		/*
		 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
		 * to work around bugs in some JS interpreters.
		 */
		function safe_add(x, y){
		  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
		  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
		  return (msw << 16) | (lsw & 0xFFFF);
		}

		/*
		 * Bitwise rotate a 32-bit number to the left.
		 */
		function rol(num, cnt){
		  return (num << cnt) | (num >>> (32 - cnt));
		}

		/*
		 * Convert an 8-bit or 16-bit string to an array of big-endian words
		 * In 8-bit function, characters >255 have their hi-byte silently ignored.
		 */
		function str2binb(str){
		  var bin = Array();
		  var mask = (1 << chrsz) - 1;
		  for(var i = 0; i < str.length * chrsz; i += chrsz)
			bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
		  return bin;
		}

		/*
		 * Convert an array of big-endian words to a string
		 */
		function binb2str(bin){
		  var str = "";
		  var mask = (1 << chrsz) - 1;
		  for(var i = 0; i < bin.length * 32; i += chrsz)
			str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
		  return str;
		}

		/*
		 * Convert an array of big-endian words to a hex string.
		 */
		function binb2hex(binarray){
		  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
		  var str = "";
		  for(var i = 0; i < binarray.length * 4; i++){
			str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
				   hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
		  }
		  return str;
		}

		/*
		 * Convert an array of big-endian words to a base-64 string
		 */
		function binb2b64(binarray){
		  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		  var str = "";
		  for(var i = 0; i < binarray.length * 4; i += 3){
			var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
						| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
						|  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
			for(var j = 0; j < 4; j++){
			  if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
			  else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
			}
		  }
		  return str;
		}		
		
		//实例化
		return hex_sha1(string);
	}
	
	
	/*
		将字符串MD5加密
		string		源字符串
	*/
	Mo.md5 = function(string){
		/*
		 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
		 * Digest Algorithm, as defined in RFC 1321.
		 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
		 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
		 * Distributed under the BSD License
		 * See http://pajhome.org.uk/crypt/md5 for more info.
		 */

		/*
		 * Configurable variables. You may need to tweak these to be compatible with
		 * the server-side, but the defaults work in most cases.
		 */
		var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
		var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
		var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

		/*
		 * These are the functions you'll usually want to call
		 * They take string arguments and return either hex or base-64 encoded strings
		 */
		function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
		function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
		function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
		function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
		function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
		function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }

		/*
		 * Perform a simple self-test to see if the VM is working
		 */
		function md5_vm_test(){
		  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
		}

		/*
		 * Calculate the MD5 of an array of little-endian words, and a bit length
		 */
		function core_md5(x, len){
		  /* append padding */
		  x[len >> 5] |= 0x80 << ((len) % 32);
		  x[(((len + 64) >>> 9) << 4) + 14] = len;

		  var a =  1732584193;
		  var b = -271733879;
		  var c = -1732584194;
		  var d =  271733878;

		  for(var i = 0; i < x.length; i += 16){
			var olda = a;
			var oldb = b;
			var oldc = c;
			var oldd = d;

			a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
			d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
			c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
			b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
			a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
			d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
			c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
			b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
			a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
			d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
			c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
			b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
			a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
			d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
			c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
			b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

			a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
			d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
			c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
			b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
			a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
			d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
			c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
			b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
			a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
			d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
			c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
			b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
			a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
			d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
			c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
			b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

			a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
			d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
			c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
			b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
			a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
			d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
			c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
			b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
			a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
			d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
			c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
			b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
			a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
			d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
			c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
			b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

			a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
			d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
			c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
			b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
			a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
			d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
			c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
			b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
			a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
			d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
			c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
			b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
			a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
			d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
			c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
			b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

			a = safe_add(a, olda);
			b = safe_add(b, oldb);
			c = safe_add(c, oldc);
			d = safe_add(d, oldd);
		  }
		  return Array(a, b, c, d);

		}

		/*
		 * These functions implement the four basic operations the algorithm uses.
		 */
		function md5_cmn(q, a, b, x, s, t){
		  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
		}
		function md5_ff(a, b, c, d, x, s, t){
		  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
		}
		function md5_gg(a, b, c, d, x, s, t){
		  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
		}
		function md5_hh(a, b, c, d, x, s, t){
		  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
		}
		function md5_ii(a, b, c, d, x, s, t){
		  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
		}

		/*
		 * Calculate the HMAC-MD5, of a key and some data
		 */
		function core_hmac_md5(key, data){
		  var bkey = str2binl(key);
		  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

		  var ipad = Array(16), opad = Array(16);
		  for(var i = 0; i < 16; i++){
			ipad[i] = bkey[i] ^ 0x36363636;
			opad[i] = bkey[i] ^ 0x5C5C5C5C;
		  }

		  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
		  return core_md5(opad.concat(hash), 512 + 128);
		}

		/*
		 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
		 * to work around bugs in some JS interpreters.
		 */
		function safe_add(x, y){
		  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
		  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
		  return (msw << 16) | (lsw & 0xFFFF);
		}

		/*
		 * Bitwise rotate a 32-bit number to the left.
		 */
		function bit_rol(num, cnt){
		  return (num << cnt) | (num >>> (32 - cnt));
		}

		/*
		 * Convert a string to an array of little-endian words
		 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
		 */
		function str2binl(str){
		  var bin = Array();
		  var mask = (1 << chrsz) - 1;
		  for(var i = 0; i < str.length * chrsz; i += chrsz)
			bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
		  return bin;
		}

		/*
		 * Convert an array of little-endian words to a string
		 */
		function binl2str(bin){
		  var str = "";
		  var mask = (1 << chrsz) - 1;
		  for(var i = 0; i < bin.length * 32; i += chrsz)
			str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
		  return str;
		}

		/*
		 * Convert an array of little-endian words to a hex string.
		 */
		function binl2hex(binarray){
		  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
		  var str = "";
		  for(var i = 0; i < binarray.length * 4; i++){
			str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
				   hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
		  }
		  return str;
		}

		/*
		 * Convert an array of little-endian words to a base-64 string
		 */
		function binl2b64(binarray){
		  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		  var str = "";
		  for(var i = 0; i < binarray.length * 4; i += 3){
			var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
						| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
						|  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
			for(var j = 0; j < 4; j++){
			  if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
			  else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
			}
		  }
		  return str;
		}
		
		//实例化
		return hex_md5(string);
	}
	
	//Mo
	
	//return this;
	
//})();
